package com.baor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baor.dao.MenuDao;
import com.baor.dao.RoleDao;
import com.baor.dao.UserDao;
import com.baor.domain.LoginUser;
import com.baor.domain.RoleVo;
import com.baor.domain.UserVo;
import com.baor.service.MenuService;
import com.baor.service.UserService;
import com.baor.service.security.TokenService;
import com.baor.utils.AjaxResult;
import com.baor.utils.MD5Utils;
import com.baor.utils.RedisUtil;
import com.github.yulichang.base.mapper.MPJJoinMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.catalina.User;
import org.apache.ibatis.ognl.IntHashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleDao roleDao;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private MenuService menuService;

    @Override
    public AjaxResult<?> selectUserList(Map<String, Object> param) {
        List<UserVo> list = userDao.selectUserList(param);
        Map<String, Object> map = new HashMap<>();
        map.put("userList", list);
        map.put("pageCount", userDao.pageCount(param));
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult<?> insertUser(Map<String, Object> params) {
        params.put("userPassword", passwordEncoder.encode(params.get("userPassword").toString()));
//        LambdaQueryWrapper<UserVo> lqw = new LambdaQueryWrapper<>();
//        lqw.eq(UserVo::getUserAccount,params.get("userAccount"));
//        UserVo user = userDao.selectOne(lqw);
//        if(user != null){
//            return AjaxResult.error("该账号已存在");
//        }
        // 验重
        List<UserVo> check = userDao.checkAccount(params);
        if (check != null && !check.isEmpty()) {
            return AjaxResult.error("该账号已存在");
        }
        //添加
        int row = userDao.addUser(params);
        int row1 = 0;
        Integer userId = userDao.selectUserId(params);
        params.put("userId", userId);
        List<Integer> userRole = (List<Integer>) params.get("userRole");
        for (int i = 0; i < userRole.size(); i++) {
            params.put("userRole", userRole.get(i));
            row1 = userDao.addUserRole(params);
        }
        if (row > 0 && row1 > 0) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult<?> roleList() {
        LambdaQueryWrapper<RoleVo> lqw = new LambdaQueryWrapper<>();
        lqw.notIn(RoleVo::getRoleId, 1);
        lqw.select(RoleVo.class, x -> !x.getColumn().equals("menu_role") && !x.getColumn().equals("role_superiors"));
        List<RoleVo> list = roleDao.selectList(lqw);
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult<?> userInfo(int userId) {
        UserVo vo = userDao.userInfo(userId);
        return AjaxResult.success(vo);
    }

    @Override
    @Transactional
    public AjaxResult<?> updateUser(Map<String, Object> param) {
        List<Integer> list = (List<Integer>) param.get("roleIds");
        int row2 = userDao.deleteRole((Integer) param.get("userId"));
        for (Integer id : list) {
            Map<String, Object> param1 = new HashMap<>();
            param1.put("roleId", id);
            param1.put("userId", param.get("userId"));
            userDao.insertRole(param1);
        }
        param.put("userPassword", passwordEncoder.encode(param.get("userPassword").toString()));
        int row = userDao.updata(param);
        if (row > 0) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult<?> delete(int userId) {
        UserVo vo = new UserVo();
        vo.setUserId(userId);
        vo.setDelflag(1);
        int row = userDao.updateById(vo);
        if (row > 0) {
            return AjaxResult.success();
        } else {
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult<?> selectSuper(Map<String, Object> params) {
        List<Integer> superId = userDao.selectSuperId(params);
        Map<String, Object> res = new HashMap<>();
        for (int i = 0; i < superId.size(); i++) {
            params.put("roleId", superId.get(i));
            res.put("userVo" + i, userDao.selectSuperName(params));
        }
        return AjaxResult.success(res);
    }

    @Override

    public AjaxResult<?> login(Map<String, Object> param) {
        System.out.println("login");
        Map<String, Object> res = new HashMap<>();
        Authentication authentication = null;
        try {
            authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(param.get("userAccount"), param.get("userPassword"))
            );
        } catch (RuntimeException ex) {
            System.out.println("出异常了");
            return AjaxResult.error();
        }
        LoginUser user = (LoginUser) authentication.getPrincipal();
        String authorization = this.tokenService.getToken(user.getVo());
        this.redisUtil.setValue("loginUser:" + user.getUserAccount(), user);
        this.redisUtil.setValue(user.getUsername(), authorization);
        res.put("userAccount", user.getUserAccount());
        res.put("userName", user.getUsername());
        res.put("userId", user.getVo().getUserId());
        res.put("authorization", authorization);
        res.put("menuList", menuService.menu(user.getVo().getUserId()));
        return AjaxResult.success(res);
    }

    @Override
    public AjaxResult<?> logOut(String userAccount) {
        String key = "loginUser:" + userAccount;
        redisUtil.delKey(key);
        return AjaxResult.success();
    }


}
